package com.cj.stock.service.impl;

import com.cj.common.exception.BaseException;
import com.cj.common.utils.StrUtil;
import com.cj.stock.service.SpikeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Author cheng jun
 * @Description:
 * @Date 2021/8/8 16:56
 */
@Service("level2SpikeServiceImpl")
@Slf4j
public class Level2SpikeServiceImpl implements SpikeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    @Async("taskExecutor")
    public boolean spikeStock() {
        // 分布式锁(同时设置锁的时间，避免程序执行中系统宕机后死锁的情况发生)
        String distributedLock = "distributedLock";
        String lock = StrUtil.getUuid32();
        Boolean lockBoolean = redisTemplate.opsForValue().setIfAbsent(distributedLock, lock, 10, TimeUnit.SECONDS);
        if (null != lockBoolean && !lockBoolean) {
            throw new BaseException("供不应求");
        }

        try {
            String inStock = "inStock";
            // 从redis拿库存
            int Stock = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(inStock)));
            if (Stock > 0) {
                // 重新设置库存大小
                int realStock = Stock - 1;
                redisTemplate.opsForValue().set(inStock, realStock);
                log.info("减库存成功,剩余库存数:" + realStock);
            } else {
                log.info("库存不够");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw e;
        } finally {
            // 释放锁(不管业务代码是否执行成功，都要释放锁)-----只有设置这把锁的线程才能释放这把锁
            if (Objects.equals(lock, redisTemplate.opsForValue().get(distributedLock))) {
                redisTemplate.delete(distributedLock);
            }
        }

        return true;
    }
}
